package com.fy.fyai.service.downloaddecorator.decorator.rate;

import com.fy.fyai.service.downloaddecorator.AbstractDownloadDecorator;
import com.fy.fyai.service.downloaddecorator.DownloadComponent;
import com.fy.fyai.service.downloaddecorator.component.FileInfo;
import com.fy.fyai.service.downloaddecorator.rate.RateLimiter;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

/**
 * @author fwq
 * @description 限流装饰器（统一装饰器，通过参数控制速度）
 * @date 2025-11-03 21:20
 */
@Slf4j
public class RateLimitDecorator extends AbstractDownloadDecorator {
    
    /**
     * 限流速度（字节/秒）
     */
    private final long bytesPerSecond;
    
    /**
     * 限流器
     */
    private final RateLimiter rateLimiter;
    
    /**
     * 构造函数
     * 
     * @param downloadComponent 被装饰的下载组件
     * @param bytesPerSecond 限流速度（字节/秒），-1表示不限流
     * @param rateLimiter 限流器实现
     */
    public RateLimitDecorator(DownloadComponent downloadComponent, long bytesPerSecond, RateLimiter rateLimiter) {
        super(downloadComponent);
        this.bytesPerSecond = bytesPerSecond;
        this.rateLimiter = rateLimiter;
    }

    /**
     * 限流增强：对输入流进行限流处理
     * 
     * @param fileId 文件ID
     * @param fileInfo 被装饰组件返回的文件信息
     * @return 限流后的文件信息
     */
    @Override
    protected FileInfo enhanceDownload(String fileId, FileInfo fileInfo) {
        if (fileInfo == null || fileInfo.getInputStream() == null) {
            log.warn("限流装饰器：文件信息为空，跳过限流处理");
            return fileInfo;
        }
        
        // 如果不需要限流，直接返回
        if (!rateLimiter.needLimit(bytesPerSecond)) {
            log.info("限流装饰器：不限流，直接返回");
            return fileInfo;
        }
        
        try {
            log.info("限流装饰器：对文件 {} 进行限流，速度限制: {} bytes/秒", fileId, bytesPerSecond);
            
            // 使用限流器对输入流进行限流处理
            var limitedInputStream = rateLimiter.limit(fileInfo.getInputStream(), bytesPerSecond);
            
            // 返回限流后的文件信息
            return new FileInfo(
                limitedInputStream,
                fileInfo.getFileName(),
                fileInfo.getFileSize(),
                fileInfo.getContentType()
            );
            
        } catch (IOException e) {
            log.error("限流装饰器：限流处理失败", e);
            throw new RuntimeException("限流处理失败", e);
        }
    }
}
